#include <err.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <string.h>
#include <dirent.h>
#include <vector>
#include <string>
#include <iostream>
#include <poll.h>
#include <signal.h>
#include <pthread.h>
#include <atomic>

#include "virtualkey.h"

VirtualKey::VirtualKey()
{
    uinputFd=-1;
    initFd();
}
VirtualKey::~VirtualKey()
{
    closeFd();
}

void VirtualKey::moveMouse(int x, int y)
{
    if(uinputFd>=0)
    {
        toemit(uinputFd, EV_REL, REL_X, x);
        toemit(uinputFd, EV_REL, REL_Y, y);
        toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
        usleep(15000);
    }
}
void VirtualKey::absMouse(int absx, int absy)
{
    if(uinputFd>=0)
    {
        toemit(uinputFd, EV_ABS, ABS_X, absx);
        toemit(uinputFd, EV_ABS, ABS_Y, absy);
        toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
        usleep(15000);
    }
}
/**
 * @brief VirtualKey::keyPress 按下
 * @param code
 */
void VirtualKey::keyPress(int code)
{
    if(uinputFd>=0)
    {
        toemit(uinputFd, EV_KEY, code, 1);
        toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
        usleep(15000);
    }
}
/**
 * @brief VirtualKey::keyRelease 弹回
 * @param code
 */
void VirtualKey::keyRelease(int code)
{
    if(uinputFd>=0)
    {
        toemit(uinputFd, EV_KEY, code, 0);
           toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
           usleep(15000);
    }
}
/**
 * @brief VirtualKey::key 输入键
 * @param code
 */
void VirtualKey::button(int code)
{
    if(uinputFd>=0)
    {
        toemit(uinputFd, EV_KEY, code, 1);
           toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
           toemit(uinputFd, EV_KEY, code, 0);
           toemit(uinputFd, EV_SYN, SYN_REPORT, 0);
        usleep(15000);
    }
}

void VirtualKey::toemit(int fd, int type, int code, int val)
{
       struct input_event ie;
       ie.type = type;
       ie.code = code;
       ie.value = val;
       /* timestamp values below are ignored */
       ie.time.tv_sec = 0;
       ie.time.tv_usec = 0;

        write(fd, &ie, sizeof(ie));
}


void VirtualKey::initFd()
{
    //struct uinput_setup usetup;
    struct uinput_user_dev usetup;

     uinputFd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if(uinputFd<0)
    {
        std::cout<<"权限不足,打开虚拟输入设备出错..."<<std::endl;
        return;
    }
       /* enable mouse button left and relative events */
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_LEFT);//左键

       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_RIGHT);//右键

       ioctl(uinputFd, UI_SET_EVBIT, EV_REL);
       ioctl(uinputFd, UI_SET_RELBIT, REL_X);
       ioctl(uinputFd, UI_SET_RELBIT, REL_Y);

       ioctl(uinputFd, UI_SET_EVBIT, EV_ABS);
       ioctl(uinputFd, UI_SET_ABSBIT, ABS_X);
       ioctl(uinputFd, UI_SET_ABSBIT, ABS_Y);

       /*数字字母键*/
       for (int i=0; i < 256; i++) {
           ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
            ioctl(uinputFd, UI_SET_KEYBIT, i);
       }
       /*
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_1);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_2);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_3);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_4);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_5);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_6);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_7);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_8);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_9);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_0);

       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_A);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_B);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_C);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_D);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_E);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_F);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_G);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_H);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_I);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_J);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_K);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_L);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_M);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_N);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_O);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_P);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_Q);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_R);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_S);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_T);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_U);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_V);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_W);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_X);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_Y);
       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_Z);

       ioctl(uinputFd, UI_SET_EVBIT, EV_KEY);
       ioctl(uinputFd, UI_SET_KEYBIT, KEY_SPACE);

       ioctl(uinputFd, UI_SET_KEYBIT, BTN_MOUSE);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_TOUCH);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_MOUSE);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_LEFT);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_MIDDLE);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_RIGHT);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_FORWARD);
       ioctl(uinputFd, UI_SET_KEYBIT, BTN_BACK);
        */
       memset(&usetup, 0, sizeof(usetup));
       usetup.id.bustype = BUS_USB;
       usetup.id.vendor = 0x1234; /* sample vendor */
       usetup.id.product = 0x5678; /* sample product */
       strcpy(usetup.name, "Example device");

       //ioctl(uinputFd, UI_DEV_SETUP, &usetup);
       write(uinputFd,&usetup,sizeof(usetup));
       ioctl(uinputFd, UI_DEV_CREATE);

       /*
        * On UI_DEV_CREATE the kernel will create the device node for this
        * device. We are inserting a pause here so that userspace has time
        * to detect, initialize the new device, and can start listening to
        * the event, otherwise it will not notice the event we are about
        * to send. This pause is only needed in our example code!
        */
       sleep(1);
}
void VirtualKey::closeFd()
{
    if(uinputFd>=0){
    ioctl(uinputFd, UI_DEV_DESTROY);
       close(uinputFd);
    }
    sleep(1);
}
bool VirtualKey::isDev()
{
    if(uinputFd>=0)
        return true;
    else
        return false;
}
